﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using JigLibX.Physics;
using JigLibX.Geometry;
using JigLibX.Collision;
using JigLibX.Math;
using JigLibX.Vehicles;

namespace LloydGame
{
    public class CoinObject : GameObject
    {
        private int m_value;
        private TimeSpan m_timeTaken;
        private float m_spinangle = 0.0f;
        private float m_jumpangle = 0.0f;
        private Vector3 m_orginal_pos;
        private float m_timeSinceLastEmittedStar = 0;
        private List<Particle> m_glowParticles;

        #region Properties
        public int value
        {
            get { return m_value; }
        }
        public TimeSpan timeTaken
        {
            get { return m_timeTaken; }
        }
        public Vector3 original_pos
        {
            get { return m_orginal_pos; }
        }
        #endregion Properties

        public CoinObject( Game p_game, GameWorld p_gameWorld, String p_objectType, Vector3 p_position
                         , Vector3 p_rotation, Vector3 p_scale, bool p_staticFlag, String p_alias, String p_coinValue) 
            : base(p_game, p_gameWorld, p_objectType, p_position, p_rotation, p_scale, p_staticFlag, p_alias)
        {
            m_value = int.Parse(p_coinValue, CultureInfo.InvariantCulture.NumberFormat);
            m_orginal_pos = p_position;
            m_glowParticles = p_gameWorld.glowParticleSystem.spawnParticles(3, Vector3.Zero, Vector3.Zero, this);
        }

        protected override bool collision_callbackFn(CollisionSkin skin0, CollisionSkin skin1)
        {
            GameObject obj0 = ((Game1)Game).gameWorld.GetObject(skin0.Owner);
            GameObject obj1 = ((Game1)Game).gameWorld.GetObject(skin1.Owner);

            if (obj0 == null || obj1 == null)
            {
                //Console.WriteLine("This should not happen! :S");
                return false;
            }
            if (obj0 == this && obj1.alias == "LocalCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj0))
            {
                ((Game1)Game).gameWorld.markForRemoval(obj0);
                ((Game1)Game).gameWorld.CoinsToSpawn.Add(this);
                ((Game1)Game).gameWorld.gamePlayer.points += m_value;
                m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                ((Game1)Game).soundBank.PlayCue("cash_register");
            }
            else if (obj1 == this && obj0.alias == "LocalCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj1))
            {
                ((Game1)Game).gameWorld.markForRemoval(obj1);
                ((Game1)Game).gameWorld.CoinsToSpawn.Add(this);
                ((Game1)Game).gameWorld.gamePlayer.points += m_value;
                m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
                ((Game1)Game).soundBank.PlayCue("cash_register");
            }
            else if (obj0 == this && obj1.alias == "RemoteCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj0))
            {
                //CarObject car = ((Game1)Game).gameWorld.GetCarObject(obj1.body);
                foreach (GamePlayer t_gamer in ((Game1)Game).gameWorld.remotePlayers)
                {
                    if (t_gamer.carObject.body == obj1.body)
                    {
                        t_gamer.points += m_value;
                        break;
                    }
                }
                //((Game1)Game).gameWorld.GetRemotePlayer(car).points += m_value;
                ((Game1)Game).gameWorld.markForRemoval(obj0);
                ((Game1)Game).gameWorld.CoinsToSpawn.Add(this);
                m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
            }
            else if (obj1 == this && obj0.alias == "RemoteCar" && !((Game1)Game).gameWorld.objectsToRemove.Contains(obj1))
            {
                //CarObject car = ((Game1)Game).gameWorld.GetCarObject(obj0.body);
                //((Game1)Game).gameWorld.GetRemotePlayer(car).points += m_value;
                foreach (GamePlayer t_gamer in ((Game1)Game).gameWorld.remotePlayers)
                {
                    if (t_gamer.carObject.body == obj0.body)
                    {
                        t_gamer.points += m_value;
                        break;
                    }
                }
                ((Game1)Game).gameWorld.markForRemoval(obj1);
                ((Game1)Game).gameWorld.CoinsToSpawn.Add(this);
                m_timeTaken = ((Game1)Game).gameTime.TotalRealTime;
            }

            return base.collision_callbackFn(skin0, skin1);
        }
        
        #region Update
        // update the object
        public override void Update(GameTime p_gameTime)
        {
            if (!((Game1)Game).gameWorld.isDebug)
            {
                m_jumpangle += p_gameTime.ElapsedGameTime.Milliseconds * 0.002f;
            }

            m_position = m_orginal_pos;
            m_position.Y += Math.Abs(((float)Math.Sin((double)m_jumpangle)) * 1.2f);

            m_body.MoveTo(m_orginal_pos, Matrix.Identity);

            Matrix o = m_skin.GetPrimitiveLocal(0).Transform.Orientation;

            m_rotation.X = MathHelper.WrapAngle((float)-Math.Asin(MathHelper.Clamp(o.M32, -1.0f, 1.0f)));
            m_rotation.Y = MathHelper.WrapAngle((float)Math.Atan2(o.M31, o.M33));
            m_rotation.Z = MathHelper.WrapAngle((float)Math.Atan2(o.M12, o.M22));

            o = m_body.Orientation;

            m_rotation.X += MathHelper.WrapAngle((float)-Math.Asin(MathHelper.Clamp(o.M32, -1.0f, 1.0f)));
            m_rotation.Y += MathHelper.WrapAngle((float)Math.Atan2(o.M31, o.M33));
            m_rotation.Z += MathHelper.WrapAngle((float)Math.Atan2(o.M12, o.M22));

            m_rotation.Y = m_jumpangle;

            if (!((Game1)Game).gameWorld.CoinsToSpawn.Contains(this))
            {
                foreach (Particle p in m_glowParticles)
                    p.active = true;

                m_timeSinceLastEmittedStar += p_gameTime.ElapsedGameTime.Milliseconds;
                while (m_timeSinceLastEmittedStar > 200)
                {
                    ((Game1)Game).gameWorld.starParticleSystem.spawnParticles(1, m_position, Vector3.Zero, null);

                    m_timeSinceLastEmittedStar -= 200;
                }
            }
            else
            {
                foreach (Particle p in m_glowParticles)
                    p.active = false;
            }

            foreach (CollisionInfo collInfo in m_body.CollisionSkin.Collisions)
            {
                if (collInfo == null)
                {
                    continue;
                }

                if (collInfo.SkinInfo.Skin0 != null && collInfo.SkinInfo.Skin1 != null)
                {
                    //collision_callbackFn(collInfo.SkinInfo.Skin0, collInfo.SkinInfo.Skin1);
                }
            }
        }
        #endregion Update
    }
}
